package org.apache.catalina.startup;

import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterInfoDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.descriptor.web.ServletDef;
import org.apache.tomcat.util.descriptor.web.ServletInfoDef;
import org.apache.tomcat.util.descriptor.web.ServletMappingDef;
import org.apache.tomcat.util.descriptor.web.SessionConfig;
import org.apache.tomcat.util.descriptor.web.WebXml;

import com.github.netty.core.util.ResourceManager;
import com.github.netty.protocol.HttpServletProtocol;
import com.github.netty.protocol.servlet.ServletContext;
import com.github.netty.webapp.WebAnnotationsLoader;

/**
 * TODO: copy from ContextConfig.webConfig()
 */
public class ServletContextConfig {
	private static final Log log = LogFactory.getLog(ServletContextConfig.class);
	/**
	 * The string resources for this package.
	 */
//    private static final StringManager sm = StringManager.getManager(Constants.Package);

	private final ResourceManager resourceManager;
	private ServletContext servletContext;
	private String[] basePackage=new String[0];
//	private boolean ok;
	private int port=8080;

	public ServletContextConfig(ServletContext servletContext) {
		this.servletContext = servletContext;
		this.resourceManager = servletContext.getResourceManager();
		
		try(InputStream input = resourceManager.getResourceAsStream("jnetty_server_jsp.properties");){
			if(input!=null) {
				Properties prop = new Properties();
				prop.load(input);
				String p = prop.getProperty("http.port");
				port=Integer.parseInt(p);
				String b = prop.getProperty("basePackage");
				basePackage = b.split(",");
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		webXmlConfig();
	}

	private void webXmlConfig() {
		WebAnnotationsLoader webaLoader = new WebAnnotationsLoader(servletContext.getClassLoader());
		Map<String, ServletInfoDef> servlets = webaLoader.getServlets();
		Map<String, FilterInfoDef> filters = webaLoader.getFilters();
		
		for(String bp:basePackage) {
			webaLoader.scanAnnotations(bp);
			servlets.forEach((k, v) -> {
				ServletContextUtil.set(v, servletContext);
			});
			filters.forEach((k, v) -> {
				ServletContextUtil.set(v, servletContext);
			});
		}
		

		if (resourceManager == null) {
			log.warn("resourceManager is null");
			return;
		}
		WebXml webXml = WebXmlUtil.getWebXml(servletContext);
		if (webXml == null) {
			return;
		}
		Map<String, String> servletMappings = webXml.getServletMappings();// ("/foo", "b");
		Map<String, Set<String>> servletUrlPatten = new HashMap<>();

		servletMappings.forEach((k, v) -> {
			Set<String> urls = servletUrlPatten.get(v);
			if (urls == null) {
				urls = new HashSet<>();
			}
			urls.add(k);
			servletUrlPatten.put(v, urls);
		});
		servlets.clear();
		Map<String, ServletDef> sds = webXml.getServlets();
		servletUrlPatten.forEach((k, v) -> {
			ServletDef s = sds.get(k);
			ServletMappingDef smd = new ServletMappingDef();
			smd.setServletName(k);
			smd.setUrlPatterns(v);
			ServletInfoDef sid = new ServletInfoDef(s, smd);
			servlets.put(k, sid);
		});
		Set<FilterMap> fms = webXml.getFilterMappings();
		Map<String, FilterDef> fdm = webXml.getFilters();
		filters.clear();
		fms.forEach((k) -> {
			String fn = k.getFilterName();
			FilterDef f = fdm.get(fn);
			FilterInfoDef fid = new FilterInfoDef(f, k);
			filters.put(fn, fid);
		});
		servlets.forEach((k, v) -> {
			ServletContextUtil.set(v, servletContext);
		});
		filters.forEach((k, v) -> {
			ServletContextUtil.set(v, servletContext);
		});
		SessionConfig sc = webXml.getSessionConfig();
		if (sc != null) {
			servletContext.setSessionTimeout(sc.getSessionTimeout());
			servletContext.setSessionTrackingModes(sc.getSessionTrackingModes());
		}
//		Set<String> wfs = webXml.getWelcomeFiles();
//		TODO JSP Servlet Config
	}
	
	protected HttpServletProtocol getHttpServletProtocol() {
		return new HttpServletProtocol(servletContext);
	}
	
//	protected abstract void servletContextOtherConfig() 
	
	protected int getPort() {
		return port;
	}

}
